#include "../src/mkvPlayer.hpp"
#include "../src/ReadJoint.hpp"
#include "../src/UILoader.hpp"
#include "gst/gst.h"
#include <chrono>
#include <stdexcept>
#include <thread>
#include <filesystem>
#include <gst/gst.h>
#include <vector>
#include "../src/dbusClient.hpp"

bool ExitFlag=false;
UILoader ui;
dbusClient client;

class AllPlayer
{
  private:
    MKVPlayer oriVideo;
    MKVPlayer stdVideo;
    ReadJoint oriJoint;
    ReadJoint stdJoint;
    ReadJoint diffDist;
    std::jthread refreshThread;
    bool PauseFlag=false;

  public:
    std::filesystem::path stdVideoPath;
    std::filesystem::path oriVideoPath;
    std::filesystem::path oriJointPath;
    std::filesystem::path stdJointPath;
    std::filesystem::path diffDistPath;
    void Play()
    {
      if(
        !std::filesystem::exists(stdVideoPath) ||
        !std::filesystem::exists(oriVideoPath) ||
        !std::filesystem::exists(oriJointPath) ||
        !std::filesystem::exists(stdJointPath) ||
        !std::filesystem::exists(diffDistPath)
      )
        throw std::runtime_error("Can't find path");
      if(refreshThread.joinable()) return;
      oriVideo.Start(oriVideoPath,false);
      stdVideo.Start(stdVideoPath,false);
      oriJoint.Start(oriJointPath);
      stdJoint.Start(stdJointPath);
      diffDist.Start(diffDistPath);
      refreshThread=std::jthread([this](std::stop_token token){
        while(!token.stop_requested())
        {
          std::this_thread::sleep_for(std::chrono::seconds(1));
          if(PauseFlag) continue;
          try
          {
            {
              char* data=new char[6220800];
              oriVideo.GetNewImage(data);
              ui.SetOriImage(1920,1080,(unsigned char*)data);
            }
            {
              char* data=new char[6220800];
              stdVideo.GetNewImage(data);
              ui.SetStdImage(1920,1080,(unsigned char*)data);
            }
            {
              float val1,val2,val3;
              oriJoint>>val1;
              stdJoint>>val2;
              diffDist>>val3;
              ui.InputData(val1, val2, val3);
            }
          }
          catch(const PlayFinishException& e)
          {
            return;
          }
        }
      });
    }
    void Pause()
    {
      PauseFlag=true;
    }
    void Continue()
    {
      PauseFlag=false;
    }
    void Stop()
    {
      if(refreshThread.joinable())
      {
        refreshThread.request_stop();
        refreshThread.join();
      }
    }
};

AllPlayer* player;


void UIExit()
{
  ExitFlag=true;
}

void UISetStdJoint(std::string path)
{
  player->stdJointPath=path;
}

void UISetOriJoint(std::string path)
{
  player->oriJointPath=path;
}

void UISetStdVideo(std::string path)
{
  player->stdVideoPath=path;
}

void UISetOriVideo(std::string path)
{
  player->oriVideoPath=path;
}

void UISetDiffJoint(std::string path)
{
  player->diffDistPath=path;
}

void UISetContinue(bool status)
{
  if(status)
    player->Continue();
  else
   player->Pause();
}

void UISetPlay()
{
  player->Play();
}

void UISetStop()
{
  player->Stop();
}

int main(int argc,char** argv)
{
  gst_init(nullptr,nullptr);
  player=new AllPlayer();
  ui.funcSetPlay=UISetPlay;
  ui.funcSetStop=UISetStop;
  ui.funcSetContinue=UISetContinue;
  ui.funcSetOriJoint=UISetOriJoint;
  ui.funcSetStdJoint=UISetStdJoint;
  ui.funcSetOriVideo=UISetOriVideo;
  ui.funcSetStdVideo=UISetStdVideo;
  ui.funcSetDiffJoint=UISetDiffJoint;
  ui.funcUIExit=UIExit;
  ui.funcSearchHandleFinishItem=std::bind(&dbusClient::SearchHandleFinishItem,&client,std::placeholders::_1);
  ui.funcGetItemInfo=std::bind(&dbusClient::GetItemInfo,&client,std::placeholders::_1);
  ui.funcGetTaskList=std::bind(&dbusClient::GetTaskList,&client);
  ui.funcGetTaskInfo=std::bind(&dbusClient::GetTaskInfo,&client,std::placeholders::_1);
  ui.Boot();
  while(sleep(10)==0 && !ExitFlag)
    ;
}
